package com.tidu.strategy;

import com.tidu.strategy.abstractSync.AbstractSyncStrategy;
import com.tidu.utils.DbUtilsTemplate;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
import java.util.Map;

@Slf4j
@Getter
@Setter
public class CustomSqlSyncStrategy extends AbstractSyncStrategy {

    private String customSql; // 用户自定义的 SQL
    private String targetTableName; // 目标表名
    private int batchSize = 10000;
    private Long offset = 0L;

    private final DbUtilsTemplate sourceDbUtils;
    private final DbUtilsTemplate targetDbUtils;

    // 使用 BufferedSingleTableSyncStrategy 复用写入逻辑
    private final SingleTableSyncStrategy delegateStrategy;

    public CustomSqlSyncStrategy(
            DataSource sourceDataSource,
            DataSource targetDataSource,
            String customSql,
            String targetTableName) {
        super(sourceDataSource, targetDataSource);
        this.sourceDbUtils = new DbUtilsTemplate(sourceDataSource);
        this.targetDbUtils = new DbUtilsTemplate(targetDataSource);
        this.customSql = customSql;
        this.targetTableName = targetTableName;

        // 初始化委托策略
        this.delegateStrategy = new SingleTableSyncStrategy(targetTableName, sourceDataSource, targetDataSource);
        this.offset = this.delegateStrategy.getOffset(); // 获取上次同步的 offset
        createTargetTableIfNotExists(); // 自动建表
    }

    /**
     * 使用自定义 SQL 查询数据
     */
    @Override
    public List<Map<String, Object>> fetchData() {
        /*try {
            // 构建子查询
            String subQuery;
            if (lastId == 0) {
                // 首次查询
                subQuery = "(SELECT id FROM " + targetTableName + " ORDER BY id LIMIT ?) AS t2";
            } else {
                // 后续查询
                subQuery = "(SELECT id FROM " + targetTableName + " WHERE id > ? ORDER BY id LIMIT ?) AS t2";
            }

            String sql = customSql + " AS t1 JOIN " + subQuery + " ON t1.id = t2.id ORDER BY t1.id";
            if (lastId == 0) {
                return sourceDbUtils.queryForMapList(sql, batchSize);
            } else {
                return sourceDbUtils.queryForMapList(sql, lastId, batchSize);
            }
        } catch (SQLException e) {
            throw new RuntimeException("Error fetching data with custom SQL", e);
        }*/
        String sql = customSql + " LIMIT ? OFFSET ?";
        try {
            List<Map<String, Object>> list = sourceDbUtils.queryForMapList(sql, batchSize, offset);
            offset += batchSize;
            return list;
        } catch (SQLException e) {
            throw new RuntimeException("Error fetching data from source", e);
        }
    }

    /**
     * 委托给 BufferedSingleTableSyncStrategy 写入数据
     */
    @Override
    public void writeData(List<Map<String, Object>> records) {
        delegateStrategy.writeData(records); // 写入目标表
        this.offset = delegateStrategy.getOffset(); // 更新 offset
    }

    /**
     * 判断是否同步完成
     */
    @Override
    public boolean isCompleted() {
        return delegateStrategy.isCompleted();
    }

    /**
     * 获取同步进度
     */
    @Override
    public String getProgress() {
        return delegateStrategy.getProgress();
    }

    /**
     * 检查目标表是否存在，不存在则自动建表
     */
    private void createTargetTableIfNotExists() {
        try {
            if (isTableExists(targetDataSource, targetTableName)) {
                log.info("Table {} already exists in target database. Skipping creation.", targetTableName);
                return;
            }

            String createTableSql = getCreateTableSqlFromSource();
            targetDbUtils.update(createTableSql);
            log.info("Table {} created successfully in target database.", targetTableName);
        } catch (Exception e) {
            throw new RuntimeException("Error creating table in target", e);
        }
    }

    /**
     * 检查目标数据库中是否存在指定表
     */
    private boolean isTableExists(DataSource dataSource, String tableName) throws SQLException {
        String sql = "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = ?";
        Long count = targetDbUtils.queryForScalar(sql, Long.class, tableName);
        return count != null && count > 0;
    }

    /**
     * 获取源表的建表语句（用于自动建表）
     */
    private String getCreateTableSqlFromSource() {
        try (Connection conn = sourceDataSource.getConnection();
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery("SHOW CREATE TABLE " + targetTableName)) {

            if (rs.next()) {
                return rs.getString("Create Table");
            }
            throw new RuntimeException("Table " + targetTableName + " not found");
        } catch (Exception e) {
            throw new RuntimeException("Error fetching create table sql", e);
        }
    }
}
